/*
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

angular.module('zeppelinWebApp').controller('SearchResultCtrl', SearchResultCtrl)

function SearchResultCtrl ($scope, $routeParams, searchService) {
  'ngInject'

  $scope.isResult = true
  $scope.searchTerm = $routeParams.searchTerm
  let results = searchService.search({'q': $routeParams.searchTerm}).query()

  results.$promise.then(function (result) {
    $scope.notes = result.body.map(function (note) {
      // redirect to notebook when search result is a notebook itself,
      // not a paragraph
      if (!/\/paragraph\//.test(note.id)) {
        return note
      }

      note.id = note.id.replace('paragraph/', '?paragraph=') +
        '&term=' + $routeParams.searchTerm

      return note
    })
    if ($scope.notes.length === 0) {
      $scope.isResult = false
    } else {
      $scope.isResult = true
    }

    $scope.$on('$routeChangeStart', function (event, next, current) {
      if (next.originalPath !== '/search/:searchTerm') {
        searchService.searchTerm = ''
      }
    })
  })

  $scope.page = 0
  $scope.allResults = false

  $scope.highlightSearchResults = function (note) {
    return function (_editor) {
      function getEditorMode (text) {
        let editorModes = {
          'ace/mode/scala': /^%(\w*\.)?spark/,
          'ace/mode/python': /^%(\w*\.)?(pyspark|python)/,
          'ace/mode/r': /^%(\w*\.)?(r|sparkr|knitr)/,
          'ace/mode/sql': /^%(\w*\.)?\wql/,
          'ace/mode/markdown': /^%md/,
          'ace/mode/sh': /^%sh/
        }

        return Object.keys(editorModes).reduce(function (res, mode) {
          return editorModes[mode].test(text) ? mode : res
        }, 'ace/mode/scala')
      }

      let Range = ace.require('ace/range').Range

      _editor.setOption('highlightActiveLine', false)
      _editor.$blockScrolling = Infinity
      _editor.setReadOnly(true)
      _editor.renderer.setShowGutter(false)
      _editor.setTheme('ace/theme/chrome')
      _editor.getSession().setMode(getEditorMode(note.text))

      function getIndeces (term) {
        return function (str) {
          let indeces = []
          let i = -1
          while ((i = str.indexOf(term, i + 1)) >= 0) {
            indeces.push(i)
          }
          return indeces
        }
      }

      let result = ''
      if (note.header !== '') {
        result = note.header + '\n\n' + note.snippet
      } else {
        result = note.snippet
      }

      let lines = result
        .split('\n')
        .map(function (line, row) {
          let match = line.match(/<B>(.+?)<\/B>/)

          // return early if nothing to highlight
          if (!match) {
            return line
          }

          let term = match[1]
          let __line = line
            .replace(/<B>/g, '')
            .replace(/<\/B>/g, '')

          let indeces = getIndeces(term)(__line)

          indeces.forEach(function (start) {
            let end = start + term.length
            if (note.header !== '' && row === 0) {
              _editor
                .getSession()
                .addMarker(
                  new Range(row, 0, row, line.length),
                  'search-results-highlight-header',
                  'background'
                )
              _editor
                .getSession()
                .addMarker(
                  new Range(row, start, row, end),
                  'search-results-highlight',
                  'line'
                )
            } else {
              _editor
                .getSession()
                .addMarker(
                  new Range(row, start, row, end),
                  'search-results-highlight',
                  'line'
                )
            }
          })
          return __line
        })

      // resize editor based on content length
      _editor.setOption(
        'maxLines',
        lines.reduce(function (len, line) { return len + line.length }, 0)
      )

      _editor.getSession().setValue(lines.join('\n'))
    }
  }
}
